﻿using IOA.MES.Business;
using IOA.MES.Common;
using IOA.MES.EsbApi.App_Start;
using IOA.Utils;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

namespace IOA.MES.EsbApi
{
    /// <summary>
    /// 全局过滤器
    /// </summary>
    public class CommonFilter : ActionFilterAttribute, IActionFilter
    {
        private Logger logger = LogManager.GetLogger(nameof(CommonFilter));
        private Stopwatch watcher;
        private object lockObj = new object();
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            watcher = new Stopwatch();
            watcher.Start();

            base.OnActionExecuting(actionContext);
        }

        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            watcher.Stop();
            try
            {
                var request = HttpContext.Current.Request;
                if (request.Url.AbsolutePath.ToString().ToLower().Contains("common/ping"))
                {
                    base.OnActionExecuted(actionExecutedContext);
                    return;
                }

                HttpContext.Current.Request.InputStream.Position = 0;
                var length = HttpContext.Current.Request.InputStream.Length;
                var buffer = new byte[length];
                HttpContext.Current.Request.InputStream.Read(buffer, 0, (int)length);

                var dictLog = new Dictionary<string, object>();
                dictLog.Add("Url", request.Url.AbsolutePath.ToString());
                dictLog.Add("Elapsed", watcher.ElapsedMilliseconds);
                if (string.Equals(request.HttpMethod, "GET", StringComparison.CurrentCultureIgnoreCase))
                {
                    dictLog.Add("QueryString", request.Url.Query);
                }
                else if (request.ContentType.ToLower().Contains("application/json"))
                {
                    dictLog.Add("Body", Encoding.UTF8.GetString(buffer));
                }
                else
                {
                    dictLog.Add("Forms", string.Join("；", request.Form.AllKeys.Select(_ => $"{_}：{request.Form[_]}")));
                }

                if (actionExecutedContext.Exception == null)
                {
                    var response = string.Empty;
                    try
                    {
                        response = actionExecutedContext.Response.Content.ReadAsStringAsync().Result;
                    }
                    catch (Exception ex)
                    {
                        logger.Fatal(ex, $"OnActionExecuted读取Response出错：{ex.Message}");
                    }
                    dictLog.Add("Response", response);
                    logger.Info(JsonConvert.SerializeObject(dictLog));
                }
                else
                {
                    lock (lockObj)
                    {
                        if (BaseEnv.LangPackages == null || !BaseEnv.LangPackages.Any())
                        {
                            BaseEnv.LangPackages = new List<LangPackage>();
                            var langFiles = Directory.GetFiles($"{AppDomain.CurrentDomain.BaseDirectory}res");
                            var sortedFiles = new List<string>();
                            if (langFiles.Any(_ => string.Equals(Path.GetFileNameWithoutExtension(_), "vn", StringComparison.CurrentCultureIgnoreCase)))
                            {
                                sortedFiles.Add(langFiles.FirstOrDefault(_ => string.Equals(Path.GetFileNameWithoutExtension(_), "vn", StringComparison.CurrentCultureIgnoreCase)));
                            }
                            if (langFiles.Any(_ => string.Equals(Path.GetFileNameWithoutExtension(_), "zh_CN", StringComparison.CurrentCultureIgnoreCase)))
                            {
                                sortedFiles.Add(langFiles.FirstOrDefault(_ => string.Equals(Path.GetFileNameWithoutExtension(_), "zh_CN", StringComparison.CurrentCultureIgnoreCase)));
                            }
                            if (langFiles.Any(_ => string.Equals(Path.GetFileNameWithoutExtension(_), "en", StringComparison.CurrentCultureIgnoreCase)))
                            {
                                sortedFiles.Add(langFiles.FirstOrDefault(_ => string.Equals(Path.GetFileNameWithoutExtension(_), "en", StringComparison.CurrentCultureIgnoreCase)));
                            }
                            foreach (var langFile in sortedFiles)
                            {
                                var jsonStr = File.ReadAllText(langFile, Encoding.UTF8);
                                BaseEnv.LangPackages.Add(JsonConvert.DeserializeObject<LangPackage>(jsonStr));
                            }
                        }
                    }

                    var errMsg = actionExecutedContext.Exception.Message;

                    var response = new ResultJson<object>(500, "ErrCode:500\r\n服务器忙\r\nServer Error\r\nLỗi máy chủ");
                    if (actionExecutedContext.Exception is MultiLanBizException)
                    {
                        var bizException = actionExecutedContext.Exception as MultiLanBizException;
                        dictLog.Add("ErrCode", bizException.ErrCode);

                        var sbMsg = new StringBuilder();
                        foreach (var lang in BaseEnv.LangPackages)
                        {
                            var err = lang.package.FirstOrDefault(_ => _.Key == bizException.ErrCode);
                            if (err.Value != null)
                            {
                                sbMsg.AppendLine(err.Value);
                            }
                        }
                        errMsg = sbMsg.ToString().TrimEnd(new[] { '\r', '\n' }) + (string.IsNullOrWhiteSpace(bizException.ErrParas) ? string.Empty : $"：\r\n{bizException.ErrParas}");
                        response = new ResultJson<object>(bizException.ErrCode, $"ErrCode:{bizException.ErrCode}\r\n{errMsg}");
                    }

                    dictLog.Add("Response", response);
                    actionExecutedContext.Response = new HttpResponseMessage
                    {
                        StatusCode = System.Net.HttpStatusCode.OK,
                        Content = new StringContent(JsonConvert.SerializeObject(response), Encoding.UTF8, "application/json")
                    };

                    if (response.ErrCode == 500)
                    {
                        logger.Fatal(actionExecutedContext.Exception, JsonConvert.SerializeObject(dictLog));
                    }
                    else
                    {
                        logger.Warn(JsonConvert.SerializeObject(dictLog));
                    }
                }
            }
            catch (Exception ex)
            {
                logger.Fatal(ex, $"OnActionExecuted出错：{ex.Message}");
            }

            base.OnActionExecuted(actionExecutedContext);
        }
    }
}
